const { Service } = require('egg');
const moment = require('moment');
const { v4: uuidV4 } = require('uuid');

const table_name = 'dictionary';
const timeFormat = 'YYYY-MM-DD HH:mm:ss';

class DictionaryService extends Service {
  async list(parent_id, pageIndex, pageSize) {
    const knex = this.app.knex;
    try {
      const dataAsync = knex().select('uuid', 'name', 'key', 'value',
        'comment', 'sort', 'parent_id', 'is_enable')
        .from(table_name)
        .where({ is_delete: 0 });

      const countAsync = knex().count('uuid as count').from(table_name)
        .where({ is_delete: 0 });
      if (parent_id) {
        dataAsync.andWhere({ parent_id });
        countAsync.andWhere({ parent_id });
      }

      const count = await countAsync;
      const data = await dataAsync.limit(Number(pageSize))
        .offset((Number(pageIndex) - 1) * pageSize);

      return {
        count: count[0].count,
        data,
      };
    } catch (error) {
      throw error;
    }
  }

  async tree() {
    const knex = this.app.knex;
    try {
      const data = await knex(table_name)
        .select('uuid', 'name', 'key', 'value', 'comment', 'sort', 'parent_id', 'is_enable')
        .where({ is_delete: 0 });

      const tree = this.getTree(data, '0');

      return tree;

    } catch (error) {
      throw error;
    }
  }

  async insert(name, key, value, comment, parent_id, is_enable) {
    const knex = this.app.knex;
    try {
      const { id } = this.ctx.session;
      const time = moment();
      const [ is_exist ] = await knex().select('*').from(table_name)
        .where({ key });
      if (is_exist) throw new Error('key存在重复');

      const instance = {
        name, key, value, comment, parent_id, is_enable,
        uuid: uuidV4(),
        is_delete: 0,
        create_time: moment(time).format(timeFormat),
        update_time: moment(time).format(timeFormat),
        create_by: id,
        update_by: id,
      };

      await knex(table_name).insert(instance);

      return instance;
    } catch (error) {
      throw error;
    }
  }

  async update(uuid, name, key, value, comment) {
    const ctx = this.ctx;
    const knex = this.app.knex;
    try {
      const { id } = ctx.session;
      const time = moment();
      const [ instance ] = await knex(table_name).select('*').where({ uuid, is_delete: 0 });
      if (!instance) {
        throw new Error('当前已删除');
      }
      if (name) {
        instance.name = name;
      }

      if (key) {
        const repeat = await knex(table_name).select('*')
          .where({ key, is_delete: 1 })
          .andWhereNot({ uuid });

        if (repeat.length !== 0) {
          throw new Error('key重复');
        }

        instance.key = key;
      }

      if (value) {
        instance.value = value;
      }

      if (comment) {
        instance.comment = comment;
      }

      instance.update_by = id;
      instance.update_time = moment(time).format(timeFormat);

      await knex(table_name).update(instance).where({ uuid });

      return instance;
    } catch (error) {
      throw error;
    }
  }

  async enable(uuid, is_enable) {
    const knex = this.app.knex;
    try {
      const instance = await knex().select('*').from(table_name)
        .where({ uuid });
      instance.is_enable = is_enable;


      await knex(table_name).update(instance);

      return instance;
    } catch (error) {
      throw error;
    }
  }

  async move(uuid, parent_id) {
    const knex = this.app.knex;
    try {
      const instance = await knex().select('*').from(table_name)
        .where({ uuid });
      instance.parent_id = parent_id;

      await knex(table_name).update(instance);

      return instance;
    } catch (error) {
      throw error;
    }
  }

  async delete(ids) {
    const knex = this.app.knex;
    try {
      await knex().update({ is_delete: 1 }).whereIn('id', ids);
      return;
    } catch (error) {
      throw error;
    }
  }
  getTree(items, parent_id = '0') {
    try {
      const tree = [];

      items.forEach(item => {
        if (item.parent_id === parent_id) {
          const children = this.getTree(items, item.uuid);
          if (children.length) {
            item.children = children;
          }

          tree.push(item);
        }
      });

      return tree;
    } catch (error) {
      throw error;
    }
  }
}


module.exports = DictionaryService;
